package com.jvm.memory;

import java.util.ArrayList;
import java.util.List;

/*
    虚拟机栈：Stack Frame 栈帧
    程序计数器（Programe Counter）：描述执行顺序，例如多线程环境下每个线程都会执行自己对应的代码，CPU会通过核心的切换以及例如
                                    时间片轮转算法来实现线程的切换执行对应代码，需要获取对应线程的程序计数器。
    本地方法栈：主要用于执行本地方法，例如源码中标识了native关键字的方法，都是由底层C++来实现的代码。
    堆(Heap)： JVM管理的最大一块内存空间，与堆相关的一个重要概念是垃圾收集器。现代几乎所有的垃圾收集器都是采用的分代收集算法，
               所以，堆空间也基于这一点进行了相应的划分:新生代与老年代。Eden空间，From Survivor空间与To Survivor空间。Java
               堆空间在物理内存上可以是连续的，也可以是不连续的。
    方法区（Method Area）：存储元信息。永久代（Permanet Generation），从JDK1.8开始已经彻底废弃了永久代，使用元空间
                          （meta space）。元信息很少会被回收，但例如关于Class的元信息的卸载，卸载完就会被回收掉。
    运行时常量池：方法区的一部分内容。
    直接内存：Direct Memory，与Java NIO密切相关。JVN通过DirectByteBuffer来操作直接内存。



    clone  反序列化  new

    关于Java对象创建的过程：
        一.new关键字创建对象的3个步骤：
            1.在堆内存中创建出对象的实例
            2.为对象的实例成员变量赋初值
            3.将对象的引用返回

    上面第一步在堆内存分配空间的两种情况：
        一.指针碰撞：前提是堆中的空间通过一个指针分割，一侧是已经被占用的空间，一侧是未被占用的空间
        二.空闲列表：前提是堆内存空间中已被使用与未被使用的空间是交织在一起的。这时，虚拟机就需要通过一个列表来记录哪些空间是可以使用的，
             哪些空间是已被使用的，接下来找出可以容纳下新创建对象的且未被使用的空间，在此空间存放该对象，同时还要修改列表上的记录。


    对象在内存中的布局：
        1.对象头：存储对象的实例的对象信息，比如hash码
        2.实例数据（即我们在一个类中所声明的各项信息）：成员变量信息
        3.对齐填充（可选）：占位符等信息

    引用访问对象的方式：
        1.使用句柄的方式
        2.使用直接指针的方式
 */
public class MyTest1 {
    public static void main(String[] args) {
        List<MyTest1> list = new ArrayList<>();

        for(;;){
            list.add(new MyTest1());
            System.gc();
        }
    }
}
